iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
0

繼續來探討Active Record相關的面試題,Active Record除了昨天提到的migration外,還有另外一個功能是有callback。

What are callbacks?
什麼是Callback?


Callback是在物件生命週期的特定時機執行一些程式碼,例如在物件創造前(before_create)、存取後(after_save),刪掉之後(after_destroy)等等。

要是我們總是在物件生命週期的某個時間點,想要執行某些事情,就可以利用callback,例如:當創造使用者帳號的時候,將使用者的email改小寫英文字母,有點像是在說:「嘿 Active Record,當你創造出一個user物件後跟我說一聲唷,這樣我就可以在其他事情發生前執行這個方法。」

要使用callback,要像以下這種寫法

class User < ApplicationRecord
  validates :login, :email, presence: true
 
  before_validation :ensure_login_has_a_value
 
  private
    def ensure_login_has_a_value
      if login.nil?
        self.login = email unless email.blank?
      end
    end
end

在驗證前before_validation,想要先執行ensure_login_has_a_value這個方法來確定,login是有值。

如果程式碼短到一行可以寫完,也可以用block的方式來寫

class User < ApplicationRecord
  validates :login, :email, presence: true
 
  before_create do
    self.name = login.capitalize if name.blank?
  end
end

習慣上會將這些方法寫private method,以符合物件封裝的概念。

舉物件被創造時,有以下的callback可以使用,按照順序排列

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_create
  • around_create
  • after_create
  • after_save
  • after_commit/after_rollback

before與after比較好理解,around開頭的就比較難懂一點,通常是在會寫一個yield有關的方法在原本的action裡,不太常見所以先跳過不看。

更新物件時的callback

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_update
  • around_update
  • after_update
  • after_save
  • after_commit/after_rollback

可以看到與創造時特別像,值得注意的是after_save這個方法在創造與更新時都有,不過都是在特定的callback之後才會觸發(after_create/after_update)。

刪除物件時的callback

  • before_destroy
  • around_destroy
  • after_destroy
  • after_commit/after_rollback

關聯性callback

callback可以透過model之間的關聯運作,例如使用者有很多文章,當使用者被刪除的時候,屬於使用者的文章也應該被刪除,我們就試著藉由AticleUser的關聯性,來對User model加上after_destroy方法。

class User < ApplicationRecord
  has_many :articles, dependent: :destroy
end
 
class Article < ApplicationRecord
  after_destroy :log_destroy_action
 
  def log_destroy_action
    puts 'Article destroyed'
  end
end
 
>> user = User.first
=> #<User id: 1>
>> user.articles.create!
=> #<Article id: 1, user_id: 1>
>> user.destroy
Article destroyed
=> #<User id: 1>

關鍵是在User後面有dependent: :destroy這個關聯性,當user被刪除,使用者的文章也會被刪除,所以連動了article的destroy,而觸發了after_destroy這個callback。

條件式callback

也可以搭配if unless等等,寫出像下面這樣的程式碼

class Order < ApplicationRecord
  before_save :normalize_card_number, if: :paid_with_card?
end

當if後面這個方法回傳true的時候,才會執行前面這個callback。

callback這個名詞本身有點誤導,之後幾天再來多挑幾題相關的,更了解callback的應用時機吧!

你可以這樣回答:

Callback是在物件生命週期的特定時機執行一些程式碼,在物件創造、更新、刪除的前後有很多callback可以使用,例如在物件創造前(before_create)、存取後(after_save),刪掉之後(after_destroy)等等。

如果我們總是在物件生命週期的某個時間點,想要執行某些事情,就可以利用callback來完成。

參考資料

1.Rubyguide-ActiveRecord Callbacks

2.Ruby on Rail- ACTIVE RECORD CALLBACKS

3.為你自己學 Ruby on Rails-Model 驗證及回呼


上一篇
Ruby on Rails面試題挑戰 Day16 - Rails怎麼管理資料庫狀態?
下一篇
Ruby on Rails面試題挑戰 Day18 - before_save 與 after_save 使用時機有何不同?
系列文
Ruby on Rails面試題挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言